using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using MCromwell.StaffIntranet.Core;
using nhibernate = NHibernate;
using NHibernate.Criterion;
using NHibernate;

namespace MCromwell.StaffIntranet.Data.NHibernate
{
    public class NHibernateStaffRepository : IStaffRepository
    {
        
        public Staff FindBy(int id)
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();
            return session.Get<Staff>(id);
        }
        
        public IList<Staff> WithPagingFindBy(StaffSearchCriteria Criteria, int PageNumber, int PageSize, out int Total)
        {
            if (Criteria == null)
                throw new ArgumentNullException("Criteria","Criteria cannot be null");

            Total = 0;
            ISession session = NHibernateSessionManager.Instance.GetSession();
            IQuery searchQuery = session.GetNamedQuery("StaffSearchingWithPaging")
                                        .SetInt32("StartRowIndex", PageNumber)
                                        .SetInt32("MaximumRows", PageSize);

            SetParameters(Criteria, searchQuery);

            IList<Staff> foundStaff = searchQuery.List<Staff>();

            IQuery pageCountQuery = session.GetNamedQuery("SearchStaffPagingCount");
            SetParameters(Criteria, pageCountQuery);
            Total = pageCountQuery.UniqueResult<int>();

            return foundStaff;
        }

        private static void SetParameters(StaffSearchCriteria Criteria, IQuery searchQuery)
        {

            if (!string.IsNullOrEmpty(Criteria.LastName))
                searchQuery.SetString("LastName", Criteria.LastName);
            else
                searchQuery.SetString("LastName", null);

            if (!string.IsNullOrEmpty(Criteria.FirstName))
                searchQuery.SetString("FirstName", Criteria.FirstName);
            else
                searchQuery.SetString("FirstName", null);

            if (Criteria.LocationId != -1)
                searchQuery.SetInt32("LocationId", Criteria.LocationId);
            else
                searchQuery.SetInt32("LocationId", -1);
        }



        protected int Update(Staff staff)
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();

            try
            {
                NHibernateSessionManager.Instance.BeginTransaction();
                session.SaveOrUpdate(staff);
                session.Flush();
            }
            finally
            {
                NHibernateSessionManager.Instance.CommitTransaction();
            }
                        
            return staff.Id;
        }


        public int Update(Staff staff, StaffPhotoSavingOptions photoSavingOptions)
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();
                        
            if (photoSavingOptions == StaffPhotoSavingOptions.Leave)
            {
                if (staff.Id > 0)
                {
                    try
                    {
                        NHibernateSessionManager.Instance.BeginTransaction();
                        Staff existingStaff = FindBy(staff.Id);
                        staff.Photo = existingStaff.Photo;
                        session.Evict(existingStaff);
                        session.Update(staff);
                        session.Flush();
                    }
                    finally
                    {
                        NHibernateSessionManager.Instance.CommitTransaction();
                    }
                                                           
                    return staff.Id;
                }
            }

            return Update(staff);
        }

        public Staff FindWithSame(string lastname, string firstname)
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();

            Staff foundStaff = session.CreateCriteria(typeof(Staff))
                                        .Add(Expression.And(
                                                        Expression.Eq("LastName", lastname),
                                                        Expression.Eq("FirstName", firstname)))
                                        .UniqueResult<Staff>();
            session.Evict(foundStaff);
            return foundStaff;
        }

        public void DeleteStaffBy(int staffId)
        {
            ISession session = NHibernateSessionManager.Instance.GetSession();

            try
            {
                NHibernateSessionManager.Instance.BeginTransaction();
                Staff staffToDelete = session.Get<Staff>(staffId);
                if (staffToDelete != null)
                    session.Delete(staffToDelete);

                session.Flush();
            }
            finally
            {
                NHibernateSessionManager.Instance.CommitTransaction();
            }
         
        }

    }
}
